#!/bin/sh
# $Id: feedtime.cgi 43 2009-10-06 22:15:38Z lordylordy $
# TV AWK INTERFACE

# (c) Andy Lord andy@lordy.org.uk
#License GPLv3

#
# This is the front-end HTML interface for the command line feedtime.sh script.
# For description of the feedtime application refer to feedtime.sh
# This CGI is only concered with :
# Step 1)Displaying a web page with a form.
# Step 2)Calling feedtime.sh to do stuff based on form contents.
#
# The overal structure of the CGI script is based around two awk scripts.
#
# The first awk script processes any form parameters passed by the web server,
# from the previous request. (if any). This corresponds to Step 2 above.
#
# Because we dont have the luxury of perl CGI module, or PHP, it is all
# done by the awk script. This either parses the QUERY_STRING env sent by 
# the web server, OR it gets the POST data from the TEMP_FILE env.
#
# The form data is converted to an array called query[]. The END clause
# then runs the 'business logic' based on the contents of query[].
# The business logic is served by the feedtime.sh which is a command line 
# script that supports all of the functions of the application.
#
# Relevant Output is passed back to stdout, which is then picked up by 
# the 2nd awk script. This is responsible for displaying the html page,
# and creating the form. (Step1)
#
# To maintain 'session data' the query[] array from awk1 is also passed 
# over to awk2.
# Of particular note is the 'action' parameter which is the main info,
# passed between the two stages.

GAWK=/share/Apps/gawk/bin/gawk
if [ -x $GAWK ] ; then
    AWK="$GAWK --lint"
    AWK=awk
else
    AWK=awk
fi

VERSION=20091007-1
#Rename and move to googlecode
#Loop fix
#VERSION=20090614-2
#Fixed promlem with html escapes in title.
#VERSION=20090613-1
#Bugfix with feed 0
#Multi feed update
#VERSION=20090528-1
#Updated for CSI nzbget locations
#VERSION=20090421-1
#Hdx fix for ws!
#VERSION=20090207-1
#Crontab an web service improvements in install.sh
#VERSION=20090204-1
#Bug fix to WGET concurrency - only affects testing.
#Bug fix to characters in filenames.
NAME=feedtime.cgi

#Fast platform check without creating a sub-process.
if [ -d /nmt/apps ] ; then
    SUBDIR=/SATA_DISK/Apps/feedtime
else
    SUBDIR=/HARD_DISK/Apps/feedtime
fi

TV_HOME=/opt/sybhttpd/localhost.drives$SUBDIR
EXE="$TV_HOME/$NAME"
self=http://localhost.drives:8883$SUBDIR

TV_DATADIR="$TV_HOME/data"

appname=feedtime
cd "$TV_HOME"

feedtime_bin="$TV_HOME/$appname.sh"

#METHOD=GET
METHOD=POST

#Processes GET or POST parameters and also outputs them to stdout 
# <name>=<value>
#so display stage can use them.
PROCESS_FORM_VALUES() {
    INPUT=${TEMP_FILE:-/dev/null}

    export UPLOAD_DIR=/share/.nzbget/
    export UPLOAD_OWNER="nmt:nmt"

    if [ ! -d "$UPLOAD_DIR" ] ; then
        mkdir -p "$UPLOAD_DIR"
        chown -R "$UPLOAD_OWNER" "$UPLOAD_DIR"
    fi
        $AWK '

#BEGINAWK
#Set fieldNo = val for all feeds in feedIdList
function setAllFeedField(fieldNo,val,feedIdList,\
feedArray,feedIdArray,id,feed) {

    split(feedIdList,feedIdArray,g_htmlSep);

    loadFeedLines(feedArray);

    for(feed in feedArray) {
        id = index(feedArray[feed],g_feedSep);
        id = substr(feedArray[feed],1,id-1);
        print "CHECKING "id;
        if (feedIdList ~ "\\<"id"\\>" ) {
            print "FOUND "id;
            feedArray[feed] = setFeedLineField(fieldNo,val,feedArray[feed]);
        }
    }

    saveFeedLines(feedArray);
}

#Set fieldNo of feedLine to be val
function setFeedLineField(fieldNo,val,feedLine,\
feedFields,i,newLine) {

    split(feedLine,feedFields,g_feedSep);

    feedFields[fieldNo] = val;

    newLine="";

    for(i = 1 ; i in feedFields ; i++ ) {
        newLine=newLine g_feedSep feedFields[i];
    }
    newLine = substr(newLine,2);

    print "OLD "feedLine;
    print "NEW "newLine;

    return newLine;
}

function copy(from,to,\
line) {
    while((getline line < from ) > 0) {
        print line > to;
    }
    close(from);
    close(to);
    system("chown -R "ENVIRON["UPLOAD_OWNER"]" "quoteFile(to));
}

function saveFeedLines(feedArray,\
i) {
    copy(gFeedFile,gFeedFile".old");
    
    for(i in feedArray) {
        if (feedArray[i] != "") {
            print feedArray[i] > gFeedFile;
        }
    }
    close(gFeedFile);
}

#Load feeds into array - index 0..n
function loadFeedLines(feedArray,\
    feedCount) {
    feedCount=0;
    while((getline feedArray[feedCount] < gFeedFile ) > 0 ) {        
        sub(/\r/,"",feedArray[feedCount++]);
    }
    close(gFeedFile);
    return feedCount;
}

function addFeed(query,id,idList,\
idArr,i,line,f,logf) {
    
    split(idList,idArr,g_htmlSep);
    line="";
    for(i=1 ; i in idArr ; i++ ) {
         line=line g_feedSep query[idArr[i]] ; 
    }
    print id line >> gFeedFile ;
    close(gFeedFile);

    system("mkdir -p "quoteFile(feedFolder(id)));

    f = localRulesFile(id);
    if (!exists(f)) {
        logf=quoteFile("'"$TV_HOME"'/delete.log");
        system( "echo addfeed >> "logf);
        system( "date >> "logf);
        print "CHANGE_THIS_TO_MATCH_PATTERNS" > f;
        close(f);
        system( "ls -l "quoteFile(feedFolder(id))"  >> "logf);
    }

    f = globalRulesFile(id);
    if (!exists(f)) {
        print "tv-dvdrip" > f;
        close(f);
    }

}

function exists(f) {
    return system("test -f "quoteFile(f)) == 0;
} 

function run_commands(query,\
action,previousaction,feedid) {

    action = query["action"];
    previousaction = query["previousaction"];


    #print "<!-- *****["action"]************* -->"
    if(action == "start" ) {
        docmd("start");

    } else if( action == "stop" ) {
        docmd("stop");

    } else if( action == "reset" ) {
        docmd("reset *");

    } else if( action == "showhistory" ) {

        docmd("showhistory");

    } else if( action == "clearhistory" ) {

        docmd("clearhistory");

    } else if( action == "rechecknew" ) {

        docmd("reset *");
        docmd("once *");

    } else if( action == "runtest" ) {
        docmd("test " query["testpages"]);

    } else if( action == "clearlog" ) {
        docmd("clearlog");

    } else if( action == "checknew" ) {

        docmd("once *");

    } else if( action == "updatefeed" ) {

    } else if( previousaction == "editfeeds" && action == "Add" ) {
    
        add_feed(query);

    } else if( action == "deletefeeds" ) {

        delete_feed(query);
        query["action"] = "editfeeds";

    } else if( action == "testfeeds" ) {

        docmd("test "htmlIdList(query["feedlist"],"|"));

    } else if( action == "checkfeeds" ) {

        docmd("once "htmlIdList(query["feedlist"],"|"));

    } else if( action == "forcefeeds" ) {

        docmd("force "htmlIdList(query["feedlist"],"|"));

    } else if( action == "skipfeeds" ) {

        docmd("skip "htmlIdList(query["feedlist"],"|"));

    } else if( previousaction == "editfeeds" && action == "enable" ) {
        
        setAllFeedField(3,1,query["feedlist"]);
        query["action"] = previousaction;

    } else if( previousaction == "editfeeds" && action == "disable" ) {
        
        setAllFeedField(3,0,query["feedlist"]);
        query["action"] = previousaction;

    } else if( previousaction == "editfeeds" && action == "update" ) {

        update_feed(query);
        query["action"] = "editfeeds";

    } else if( previousaction == "editfeed" && action == "save" ) {

            feedid = query["feedid"];

            text2file(query["rules"], localRulesFile(feedid)  );
            text2file(query["grules"], globalRulesFile(feedid) );
            query["action"] = "editfeeds";

    } else if( previousaction == "editfeed" && action == "back" ) {

            query["action"] = "editfeeds";

    } else if( action == "configsave" ) {

            config_save(query);


    } else if( action == "download" ) {
        docmd("download \""url_decode(query["url"])"\" "quoteFile(url_decode(query["file"])));
    }
}

function add_feed(query,\
i,feedId) {
    feedId = systime();

    addFeed(query,feedId,"newfeedname"g_htmlSep"newfeedenabled"g_htmlSep"newfeedurl"g_htmlSep"newfeedcompression"g_htmlSep"newfeedpriority"g_htmlSep"newfeedlinkfind"g_htmlSep"newfeedlinkreplace");

    query["action"] = "editfeed";
    query["feedid"] = feedId;
    #Copy newfeedxxx to feedxxx.id
    for(i in query) {
        if (i ~ "^newfeed" ) {
            query[substr(i,4) "." feedId ] = query[i];
        }
    }
}

function delete_feed(query,\
i,id,feedArray,selected) {

    loadFeedLines(feedArray);

    getSelectedFeedIds(query,"feedlist",selected);

    for(i = 0 ; i in feedArray ; i++ ) {
        
        id = index(feedArray[i],g_feedSep);
        
        id = substr(feedArray[i],1,id-1);

        if (id in selected) {
            delete feedArray[i];
            deleteFeedFolder(id);
        }
    }
    saveFeedLines(feedArray);
}

function update_feed(query,\
i,feedArray,feedIds,id) {
    split(query["feedids"],feedIds,"|");

    for (i = 1 ; i in feedIds ; i++) {
        if (feedIds[i] != "" ) {
            id = feedIds[i];
            feedArray[i] = id g_feedSep query["feedname."id] g_feedSep\
             query["feedenabled."id] g_feedSep\
             query["feedurl."id] g_feedSep\
             query["feedcompression."id] g_feedSep\
             query["feedpriority."id] g_feedSep\
             query["feedlinkfind."id] g_feedSep\
             query["feedlinkreplace."id];
        }
    }
    saveFeedLines(feedArray);
}
#TODO exlcude option_ variables from self links
function config_save(query,\
option_name,value,oldvalue,real_name) {

    for (option_name in query) {
        if (match(option_name,"^option_")) {
            real_name=substr(option_name,index(option_name,"_")+1);
            value=query[option_name];
            oldvalue=query["orig_"option_name];
            if (value != oldvalue ) {
                docmd(sprintf("set %s \"%s\"",real_name,value));
            }
            delete query[option_name];
            delete query["orig_"option_name];
        }
    }
}

#if a HTML name has multiple values they are separated by \r
#Convert \r to " " so the list can be passed to a script
function htmlIdList(value,sep) {
    gsub(/\r/,sep,value);
    print "htmlIdList "value;
    return "\""value"\"";
}

#Get hash of selected feeds - index = id value=1
function getSelectedFeedIds(query,htmlId,selected,\
tmp,i) {
    delete selected;
    split(query[htmlId],tmp,"\\r");
    for(i in tmp) {
        selected[tmp[i]] = 1;
    }
}


function docmd(args) {
        print "CMD ARGS: " args ;
        system("'"$feedtime_bin"' " args " 2>&1");
}

function parse_query_string(str,dest,\
i,eq,clauses) {
    if (str != "") {
        # Note that each nzb action has format annn=action 
        # and if there is a a_nnnn=Go then nnnn is the current action.
        # However this may be changed to a mult-action format.
        split(str,clauses,"&");
        for(i in clauses) {
            #TODO Slight bug - cant cope with multi - values.
            eq=index(clauses[i],"=");
            dest[url_decode(substr(clauses[i],1,eq-1))]=url_decode(substr(clauses[i],eq+1));
        }
    }
}

function output_values(query,\
i) {
    print "FORM_PARAMS_BEGIN";
    for(i in query) {
        printf "<<%s>>=@@%s@@\n",i,query[i];
    }
    print "FORM_PARAMS_END";
}
#Copy textarea array to a file.
function text2file(text,file) {
    copy(file,file".old");
    printf "%s",text > file;
    close(file);
}

function globalRulesFile(feedid) {
    return feedFolder(feedid)"/tv.global";
}

function localRulesFile(feedid) {
    return feedFolder(feedid)"/tv.list";
}

function feedFolder(feedid) {
    return "'"$TV_HOME"'/data/feed_"feedid;
}

function log_delete(msg,\
f) {
    f="'"$TV_HOME"'/delete.log";



    print strftime("%y-%m-%d %H:%M",systime()) >> f;
    print msg >> f;
    close(f);
}

function deleteFeedFolder(feedId,
dir,backupDir) {
    backupDir=quoteFile(feedFolder(feedId)".old");
    dir=quoteFile(feedFolder(feedId));
    system("rm -fr "backupDir);
    system("mv -- "dir" "backupDir);
    log_delete("deleted feed "feedId);
}

function quoteFile(fileName,\
q) {
    q="'"'"'";
    gsub(/'"'"'/,q  "\\" q q , fileName );
    return q fileName q;
}

# Process the POST data into g_query string. No need to change this block
#this needs a re-write
function readFormData(query,
    formPostData,crlf,unix,in_data,start_data,filename,name,cmd,llen,format,boundary,counter,value,urlEncodedInPostData) {

    formPostData=ENVIRON["TEMP_FILE"];
    if (formPostData == "" ) return;

    boundary=ENVIRON["POST_BOUNDARY"]
    urlEncodedInPostData = ( g_http_method=="POST" && ENVIRON["POST_TYPE"] == "application/x-www-form-urlencoded" );
    
    crlf=1
    unix=0
    in_data=-1;
    start_data=-2;
    filename="";
    name="";
    g_has_post_data=1;

    while((getline < formPostData ) > 0 ) {

        if ( counter >= 0 ) {  counter++  ; }

        printf "POST:%s",$0;

        if ( urlEncodedInPostData ) {
            gsub(/[^:]+:/,"");
            parse_query_string($0,query);

        } else if ( index($1,boundary) ) {

            #Process outging item
            if (filename != "" ) {
                close(filename);
                cmd=sprintf("chown %s \"%s\"",ENVIRON["UPLOAD_OWNER"],filename);
                system(cmd);
            } else if (name != "") {
                if(name in query) {
                    #If name appears multiple times - separate with \r
                    query[name] = query[name] "\r" value;
                } else {
                    query[name] = value;
                }
            }

            #Start next item
            counter=0;
            filename="";
            name="";
            value="";

        } else if (counter==1 && index($0,"Content-Disposition: form-data; name=")==1 ) {

            if (match($3,"name=\"[^\"]+\"")) {
                name=substr($3,RSTART+6,RLENGTH-7);
                value="";
            }
            format=crlf;
            filename="";

            if (match($0,"filename=\".*\"")) {

                filename=substr($0,RSTART+10,RLENGTH-11);
                if (filename != "") {
                    filename=sprintf("%s/%s",ENVIRON["UPLOAD_DIR"],filename);
                    printf "" > filename; #Clobber
                }
            }
        } else if (counter==2 && index($0,"Content-Type: application") == 1) {

            format=unix;
            #print "CONTENT: $0"

        } else if (counter>0 && match($0,"^\r$")) {

            #print "END OF HEADER";
            counter=start_data; 

        } else if ( counter<0 ) {

            if (format==crlf ) {
                llen=length($0);
                if (substr($0,llen) == "\r") {
                    $0=substr($0,1,llen-1);
                }
            }

          if (filename != "") {
              printf "%s\n",$0 >> filename;
          } else if (counter == start_data) {
              value=$0;
          } else {
              value=value "\n" $0;
          }
          counter=in_data;
          #print "DATA";
        }
    }
}

#Process input
BEGIN {
    print "BEGIN";

    g_htmlSep="|";
    g_feedSep="|";

    g_tv_home="'"$TV_HOME"'"

    gFeedFile = "'"$TV_HOME"'/data/feeds";

    parse_query_string(ENVIRON["QUERY_STRING"],g_query);

    readFormData(q2);

    #Merge post data with Get data.
    for(q in q2) {
       g_query[q]=q2[q];
    }

    #This is a straight assignment g_query[name]=value except if the 
    #Name has the form action.val.n2.v2 etc In this case the following values are also set
    # g_query[action]=x and g_query[y]=z
    #This is to allow multiple submit buttons on the same form to pass different information.
    # Another approach (probably the correct one) is to use different forms but this means tracking hidden fields etc
    for(n in g_query) {
        if (index(n,"action.") == 1 ) { 
            split(n,fields,"\\.");
            for(i=1 ; i in fields ; i+=2 ) {
                g_query[fields[i]] = fields[i+1];
            }
            delete g_query[n];
        }
    }
}


function trim(x) {
    sub(/^ +/,"",x);
    sub(/ +$/,"",x);
    return x;
}

END {
    print "END";

    if (g_query["action"] == "Go") {
        #Get real action from the doaction drop down list.
        g_query["action"] = g_query["doaction"];
    }

    if ("action" in g_query) {

        g_query["action"] = trim(g_query["action"]);

        #print "INCOMING: action = "g_query["action"];
        #print "INCOMING: previousaction = "g_query["previousaction"];

        run_commands(g_query);

        #print "OUTGOING: action = "g_query["action"];
        #print "OUTGOING: previousaction = "g_query["previousaction"];
    }

    output_values(g_query);
}

function ORD_INIT(i,hex) {
    for(i=0 ; i < 255 ; i++ ) {
        c = sprintf("%c",i);
        _CHR[i]=c;
        _ORD[c]=i;
        hex=sprintf("%%%02X",i);
        _HTML[c]=hex;
        _HTML[hex]=c;
    }
}
function url_decode(str, i,c) {
  if (!(0 in _CHR)) { ORD_INIT() };
  start=1;
  print "URLIN:" str;
  while ((i=index(substr(str,start),"%")) > 0) {
      i  = (start-1)+i;
      c=toupper(substr(str,i+1,2)); # hex digits
      print "url_decode:"c;
      c=_HTML["%"c];
      print "url_decode:"c;
      str = substr(str,1,i-1) c substr(str,i+3);
      start = i+1;
  }
  print "URLOUT:" str; 
  return str;
}
    ' "$INPUT" 2>&1 
}


#TODO Only get post job info if -l says post jobs queued etc?

RELOAD_PAGE_TO_CLEAR_PARAMS() {
    cat <<HERE
Content-Type: text/html

<html><head><meta http-equiv="REFRESH" content="0;url=$1"></head><body bgcolor="#000055"></body></html>
HERE
exit 0
}

MAIN_PAGE() {

    running=0;

    #f=/share/awk.txt
    PROCESS_FORM_VALUES_OUTPUT_FILE=$TMPDIR/feedtime.cgi.$$

    #Run commands.
    PROCESS_FORM_VALUES > $PROCESS_FORM_VALUES_OUTPUT_FILE

    #Get state of the world...

    if [ -f "$TV_DATADIR/$appname.active" ] ; then
        running=1
    fi

    zebedee=0
    if [ -f /opt/sybhttpd/default/zebedee.cgi ] ; then
        zebedee=1
    fi
    unpak=0
    if [ -f /opt/sybhttpd/default/unpak.cgi ] ; then
        unpak=1
    fi

     $AWK '

function head(\
i) {
                
    print "<head><title>FeedTime '$VERSION' </title>"

    #Cant daemonize starting process properly. (dont know how to call setsid() ) so
    #reload the webpage instead.

    # text-align doesnt work on PCH.
    print "<style type=\"text/css\">";

    if(g_local_browser) {
        print "body { font-family:verdana;arial; font-size:12pt; color:white; background:#000022}";
        print ".log { font-size:10pt ; color:#CCFFFF }";
        print ".metachar { font-size:12pt ; color:#FFFF00 ; background-color:black; font-weight:bold }";
        print "td {color:white }";
        print ".control {color:#FF5555}";
        print ".rule { background-color:#002211; }"
        print ".menu { background-color:#000044; }"
        print ".grule { background-color:#220044; }"
        print ".main { background-color:#003355; }"
        print "a {color:#EE99FF }";
        print "hr {color:blue }";
        print "h1 {font-size: 14pt }";
        print ".logo { font-size:14pt ; text-decoration:underline; }"
        print ".failedmatch {font-size:10pt ; color:#FFAAAA;}"
        print ".goodmatch {font-size:10pt ; color:#AAFFAA;}"
        print ".optionrow0 { background-color:#005544; }"
        print ".optionrow1 { background-color:#004455; }"
        print ".r3 { background-color:#444444; }"
        print ".r4 { background-color:#555555; }"
        print ".r1 { background-color:#005544; }"
        print ".r2 { background-color:#004455; }"
    } else {
        print "body { font-family:verdana;arial; font-size:12pt; color:black; background:white}";
        print ".log { font-size:10pt ; color:black ; }";
        print ".metachar { font-size:12pt ; color:#blue ; background-color:#99Ff99; font-weight:bold }";
        print "td {color:black }";
        print ".control {color:#FF5555}";
        print ".rule { background-color:#EEFFFF; }"
        print ".menu { background-color:#DDDDFF; }"
        print ".grule { background-color:#FFEEEE; }"
        print ".main { background-color:#F5F5FF; }"
        print "a {color:#990099 ; font-weight:bold; }";
        print "a:hover { background-color:blue ; color:yellow ; font-weight:bold; }";
        print "hr {color:blue }";
        print "h1 {font-size: 14pt }";
        print ".logo { font-size:14pt ; font-weight:bold ; text-decoration:underline; }"
        print ".failedmatch {font-size:10pt ; color:#880000;}"
        print ".goodmatch {font-size:10pt ; color:#008800;}"
        print ".optionrow0 { background-color:#BBFFCC; }"
        print ".optionrow1 { background-color:#BBCCFF; }"
        print ".r3 { background-color:#EEEEEE; }"
        print ".r4 { background-color:#E8E8E8; }"
        print ".r1 { background-color:#BBFFCC; }"
        print ".r2 { background-color:#BBCCFF; }"
    }
    print "</style>";

    print "</head>";
    print "<!-- VERSION:'"$VERSION"' -->";
    for (i in ENVIRON) { print "<!-- ENV:" i "=" ENVIRON[i] " -->"; }
    #for (i in g_query) { print "<!-- QUERY:" i "=" g_query[i] " -->"; }
}
function timestamp() {
    return strftime("%H:%M",systime());
}
function start_control_form(previous_action) {
    printf "<form action=\"%s\" enctype=\"multipart/form-data\" method=\"'"$METHOD"'\">\n",g_self;
    print "<table class=\"control\" width=100% ><tr>";
    
    # LOGO -------------------------------------
    print "<td valign=\"top\" class=\"menu\">";
    print "<input type=hidden name=\"previousaction\" value=\""previous_action"\" />";
    print "<center>";
    printf "<span class=\"logo\"><font color=\"#FF5555\">F</font>";
    printf "<font color=\"#5555FF\">eed</font>";
    printf "<font color=\"#FF5555\">T</font>";
    printf "<font color=\"#5555FF\">ime</font></span><br>";
    print "</center><p>";
    menu();
    printf "</td>";

    # ----------------------------------------

    print "<td class=\"main\" width=85% valign=\"top\">";
}

function end_control_form() {
    print "</td></tr></table></form>"
}

function menu() {
    running='$running';
    zebedee='$zebedee';
    unpak='$unpak';



    if (!running) {
        print link("action","start","<font color=red>Start service</font>");
    } else {
        print link("action","stop","Stop service");
    }

    print "<p>" link("action","editfeeds","Manage Feeds");
    print "<p>";
    #print link("action","test","Test Patterns");
    #print "<p>";

    print link("action","config","Configure");
    print "<p>";

    print link("action","showlogs","Recent Activity");

    print "<p>";
    print link("action","showhistory","NZB History");
    print "<p>";


    if (g_local_browser && unpak) {
        print "<a href=\"http://127.0.0.1:8883/unpak.cgi\">Watch</a>&nbsp;"
    }
    if (zebedee) {
        if (g_local_browser) {
            print "/<a href=\"http://127.0.0.1:8883/zebedee.cgi\">Zebedee</a>&nbsp;"
        } else {
            print "/<a href=\"./zebedee.cgi\">Go To Zebedee</a>&nbsp;"
        }
    }
    print "<p>" link("action","clearlog","Clear Activity");
    print "<p>" link("action","clearhistory","Clear History");
    if (g_local_browser) {
        print "/<a href=\"/webservices_list.html\">Exit</a>"
    }


    print "<br>"small("V'$VERSION'");
    if (g_local_browser) {
        print small("Remote Access<br>http://ipaddress:8883/'$appname'.cgi")
    }
}
function small(x) {
    return "<font size=\"-2\">"x"</font>";
}

#Make button labels the same width
function button(name,value) {
    return sprintf("<input class=\"btn\" type=\"submit\" name=\"%s\" value=\"%s\" >\n",name,value);
}
function link(name,value,label) {
    return sprintf("<a href=\"?%s=%s\">%s</a>",name,url_encode(value),label);
}

function link2(name,value,name2,value2,label) {
    return sprintf("<a href=\"?%s=%s&%s=%s\">%s</a>",name,url_encode(value),name2,url_encode(value2),label);
}

function link3(name,value,name2,value2,name3,value3,label) {
    return sprintf("<a href=\"?%s=%s&%s=%s&%s=%s\">%s</a>",name,url_encode(value),name2,url_encode(value2),name3,url_encode(value3),label);
}

function debug(msg) {
    print "<!-- " msg " -->"
}

function globalRulesFile(feedid) {
    return feedFolder(feedid)"/tv.global";
}

function localRulesFile(feedid) {
    return feedFolder(feedid)"/tv.list";
}

function feedFolder(feedid) {
    return g_tv_home "/data/feed_"feedid;
}

#Write output
BEGIN {
    g_feedSep="|";
    g_htmlSep="|";
    g_tv_home="'"$TV_HOME"'"
    gFeedFile = g_tv_home "/data/feeds";
    print "Content-Type: text/html\n"
    g_local_browser=(ENVIRON["REMOTE_ADDR"] == "127.0.0.1" )
    if (g_local_browser) {
	    g_self="'"$self"'";
    } else {
	    g_self="/'$appname'.cgi";
    }
    #print url_encode("a%b?c d"),"<br>"; print url_decode(url_encode("a%b?c d")); exit
}

# Read the current local rules file.
function loadRules(fileName,rule,\
    rule_count,line) {
    rule_count = 0;
    while((getline line < fileName) > 0) {
        rule[rule_count++] = substr(line,index(line,":")+1);
    }
    close(fileName);
    return rule_count;
}

function show_patterns(html_name,text_size,text,rows,\
i) {
    printf "<center>";
    if (g_local_browser) {
        printf "<textarea name=\"%s\" rows=%d cols=32 >",html_name,rows/2;
    } else {
        printf "<textarea name=\"%s\" rows=%d cols=40 >",html_name,rows;
    }
    heapsort(text_size,text,1);
    for(i = 0 ; i < text_size ; i++ ) {
        print text[i];
    }
    printf "</textarea>";
    printf "</center>";
}

function start_page() {
    start_body_table();
    previous_action=g_query["action"];
    start_control_form(previous_action);
    if (previous_action == "editfeeds") {

        show_editfeed_table();

    } else if (previous_action == "editfeed") {

        show_edit_table(g_query["feedid"]);

    } else if (previous_action == "config") {

        content_title("Configuration");
        show_config_table();

    } else if (previous_action == "test") {
        content_title("Test Patterns");
        printf "<div class=\"test\">";
        print "Test TV patterns. Most RSS streams only hold a few days worth of items."
        print "For this reason the test data used is obtained"
        print "by browsing the relevant website pages directly rather than via RSS."
        print "<br>If you are getting 2 or 3 matches for some patterns and 0 matches for others, then either"
        print "<br>- There is a mistake in the pattern"
        print "<br>- The show did not show during that period."
        print "<br>Each server has different number of nzbs per page so comparisons of counts between servers is not useful.";
        print "<br>if you have 0 matches for some and only 1 or 2 matches for others. Then it may just mean you need to test more pages. ";
        print "Each 7 days should roughly increase the count by 1 or 2 depending on your filtering. Eg xvid/720."
        print "<p><b>Tests may take a while to run. Avoid clicking links more than once!</b>";
        print "The manual sites (tvbinz and feedtime ) should run tests faster than the automatic ones."
        print "<font color=\"#FF9999\" >Too many large tests may put a strain on the server, especially for automatic feeds, take a long time and may get your IP banned</font>"
        print "<center>"
        print "<table width=100%><tr><td>"
        print link2("action","runtest","testpages",1,"Test 1 page");
        print "</td><td>"link2("action","runtest","testpages",5,"Test 5 pages");
        if (!g_local_browser) {
            print "</td><td>"link2("action","runtest","testpages",10,"Test 10 pages");
            print "</td><td>"link2("action","runtest","testpages",15,"Test 15 pages");
        }
        print "</td></tr></table>"
        print "</center>"
        print "<p>If you still get zero matches for everything:"
        print "<br>a)Stop the service,"
        print "<br>b)Add a new pattern with just the text <b>xvid</b> , clear the global rules box and do a 1 page test."
        print "<b>Remove the <u>xvid</u> pattern before starting the service again!</b>,"
        print "<br>If it works then check your patterns,"
        print "<br>if it doesnt work";
        print "go to configuration and change the compression options or the source, and try again. If still no luck, report back, including any significant";
        print "details, like model number";
        print "</div>"
        #print two_buttons("runtest","cancel");
    }
    if (previous_action == "save") {
        content_title("Edit Listings");
        print "Run a test on 5-9 pages to check matching is ok. Note that matches will fail if the program is not yet aired!<br>"
        print "6 pages on feedtime is about one week<br>"
        print "9 pages on newsleech is about 3 days so some patterns may appear to fail despite being correct.<br>"
    }
}

function show_logs(title,fileName,\
line,logarr,logidx) {
   FS="\n";

   printf "" >> fileName;
   close(fileName);
   printf "" >> fileName".1";
   close(fileName".1");

   logidx = 0;
   while ((getline line < fileName) > 0) {
       logarr[++logidx] = add_log_line(line);
   }
   close(fileName);

   while ((getline line < fileName".1") > 0) {
       logarr[++logidx] = add_log_line(line);
   }
   close(fileName".1");

   reverse_log(title,logarr,logidx);
}

function add_log_line(line,\
i,tmp,name,pre,url) {

   i = match(line,"\\|https?:");
   #replace |http... in logs with a clickable link
   if (i > 0) {
       pre=substr(line,1,i-1);
       split(substr(line,i+1),tmp,"|");
       url=url_encode(tmp[1]);
       name=tmp[2];

       #Remove message part
       sub(/.* req [0-9]+/,"",name);
       sub(/[0-9][0-9]\/[0-9][0-9].*/,"",name);

       #Remove dir prefix 
       if (match(name,".*/")) {
           name = substr(name,RSTART+RLENGTH);
       }

       gsub(/[^A-Za-z0-9]+/,".",name);
       sub(/^\./,"",name);
       sub(/\.$/,"",name);

       #remove nzb suffix
       if (match(name,"\.nzb$")) {
           name = substr(name,1,RSTART-1);
       }
       name = url_encode(name);

       line = sprintf("%s <a href=\"%s?action=download&file=%s.nzb&url=%s\">%s</a>",pre,g_self,name,url,name);
   }
   return line;
}

# Show log back to front. also extract matches and display nicely (sortof)
function reverse_log(title,logarr,logidx,\
i,failedmatches,goodmatches) {
   printf "<div class=\"log\">";
   #for (i in ENVIRON) { printf "%s=%s<br>",i,ENVIRON[i]; }
    #Print the log file back to front. If we encounter the seqnece of match patterns convert it to a table.
    content_title(title);
    print "<br><i>Duplicate titles in feeds are OK. nzbget merges them together</i>";
    goodmatches="";
    failedmatches="";
    for(i=logidx ; i>=1 ;i--) {
        if(match(logarr[i],"^[0-9]+ matches")) {
            if(substr(logarr[i],1,2) == "0 ") {
                failedmatches=failedmatches "\n<br>" substr(logarr[i],index(logarr[i],"+")-2);
            } else {
                goodmatches=goodmatches "\n<br>" logarr[i];
            }
        } else {
            showmatches();
            goodmatches="";
            failedmatches="";
            if (logarr[i] != "" ) {
                printf("<br>%s\n",logarr[i]);
            }
        }
    }
    if (logidx == 0 || ( logidx==1 && logarr[1] == "" ) ) {
        print "<br>Empty";
    }
    showmatches();
    goodmatches="";
    failedmatches="";
    printf "</div>";
}

function showmatches(goodmatches,failedmatches) {
     if (goodmatches failedmatches != "") {
         if (goodmatches != "") {
             goodmatches=sprintf("<td class=\"goodmatch\" valign=\"top\"><u><b>Matched</b></u>%s</td>",goodmatches);
         }
         if (failedmatches != "") {
             failedmatches=sprintf("<td class=\"failedmatch\" valign=\"top\"><u><b>No Matches</b></u>%s</td>",failedmatches);
         }
         printf("<br><table><tr>%s%s</tr></table>",failedmatches,goodmatches);
     }
}


function show_config_table() {
    print "<div class=\"log\">";
    system("cd \""g_tv_home"\" ; ./options.sh TABLE feedtime.cfg.help data/feedtime.cfg");
    print "</div>"
    print two_buttons("configsave","cancel");
}

function content_title(t) {
    printf "<h1><center>%s</center></h1>",t;
}

function loadFeedLines(feedArray,enabled,\
feedCount,feedDetails) {
    feedCount=0;
    while((getline feedArray[feedCount] < gFeedFile ) > 0 ) {        
        sub(/\r/,"",feedArray[feedCount]);
        split(feedArray[feedCount],feedDetails,g_feedSep);


        if ((8 in feedDetails) && !(9 in feedDetails)) {
            if (enabled == "-" || enabled == feedDetails[3] ) {
                
                feedCount++;

            }
        }
    }
    close(gFeedFile);
    return feedCount+0;
}

function show_editfeed_table(\
feed,idlist,hdr,\
feedCount,feedArray,\
feedCount2,feedArray2) {

    hdr= "<td width=5%>Feed Name</td>";
    hdr = hdr "<td width=20%>RSS URL</td>";
    hdr = hdr "<td width=5%>gzip</td>";
    hdr = hdr "<td width=5%>top</td>";
    hdr = hdr "<td width=6%>Replace Link (regex).</td>";
    hdr = hdr "<td width=6%>Replace With</td><td></td>";

    print "<center><b>Manage RSS Feeds</b></center>";
    print "<br><table>";
    print "<tr class=r1><td align=right><b>RSS URL</b></td><td>Some feeds allow you to increase the number of results by modifying a count in the url (eg n=200). Useful if you want to reduce the number of checks per day</td></tr>";
    print "<tr class=r2><td align=right><b>gzip:</b></td><td> Set to Yes if the feed requires compression. Most do. Set to NO for feedtime.com and myfeedtime.foechoer.be otherwise set to yes if not sure.</td></tr>";
    print "<tr class=r1><td align=right><b>top:</b></td><td> Set to Yes to add downloads to top of nzbget queue</td></tr>"
    print "<tr class=r2><td align=right><b>Replace Link/ Replace with:</b></td><td> (Advanced) If the links in the rss feed go to the original website rather than a direct download, replacing certain characters in the link may allow direct nzb download.</td></tr>"
    print "</table>";


    feedCount = loadFeedLines(feedArray,"-");
    heapsort(feedCount,feedArray,2);

    #feedCount2 = loadFeedLines(feedArray2,0);
    #heapsort(feedCount2,feedArray2,2);

    print "<table width=100%><tr class=r4><td width=5%>Action</td>" hdr "</td></tr>";
    idlist = displayFeedLines(feedCount,feedArray);

    idlist = idlist displayFeedLines(feedCount2,feedArray2);

    print "</table>";

    print "<input type=hidden name=feedids value=\""idlist"\" />";
    print "<table><tr>";
    print "<td>"select("doaction","update",\
"update:Apply Changes\
|enable:Enable selected feeds\
|disable:Disable selected feeds\
|testfeeds:Test selected feeds\
|checkfeeds:Check selected feeds for new NZBs\
|skipfeeds:Skip over matches on selected feeds\
|forcefeeds:Force Download on selected feeds\
|nothing:-------------\
|deletefeeds:DELETE selected feeds","")" </td>";
    print "<td>"button("action","Go")"</td>";
    print "</tr></table>";

    sub(/Feed Name/,"<b>New Feed</b>",hdr);
    print hidden("newfeedenabled","1");
    print "<table width=100%><tr class=r4>"hdr"</tr>";
    print "<tr class=r3><td>"text("newfeedname","","size=10")"</td>";
    print "<td>"text("newfeedurl","","")"</td>";
    print "<td>"select("newfeedcompression","1","1:Yes|0:No","")"</td>";
    print "<td>"select("newfeedpriority","1","1:Yes|0:No","")"</td>";
    print "<td>"text("newfeedlinkfind","","size=10")"</td>";
    print "<td>"text("newfeedlinkreplace","","size=10")"</td>";
    print "<td>"button("action","Add")"</td>";
    print "</tr>";
    print "</table>";
}

function quoteFile(fileName,\
q) {
    q="'"'"'";
    gsub(/'"'"'/,q  "\\" q q , fileName );
    return q fileName q;
}

function initFeed(id,\
ff,gr,lr) {
    ff=quoteFile(feedFolder(id));
    gr=quoteFile(globalRulesFile(id));
    lr=quoteFile(localRulesFile(id));

    system("mkdir -p "ff \
    " && if [ ! -e "gr" ] ; then echo \"tv-dvdrip\" > "gr" ; fi "\
    " && if [ ! -e "lr" ] ; then echo \"CHANGE_THIS_TO_MATCH_PATTERNS\" > "lr" ; fi && chown -R nmt:nmt "ff);
}

#Display a feed line 
function displayFeedLines(feedCount,feedArray,\
i,feedDetails,feedId,feedEnabled,idlist,attr,rule_count,local_rule,grule_count,global_rule) {

    idlist = "";

    for(i = 0 ; i < feedCount ; i++ ) {
        split(feedArray[i],feedDetails,g_feedSep);
        feedId = feedDetails[1];
        feedEnabled = feedDetails[3];
        attr="";
        if (!feedEnabled) {
            attr="disabled";
        }

        initFeed(feedId);

        rule_count = loadRules(localRulesFile(feedId),local_rule);
        grule_count = loadRules(globalRulesFile(feedId),global_rule);
        print "<tr class=r"((i%2)+3)" >";
        print "<td>"checkbox("feedlist",feedId,"");
        print hidden("feedenabled."feedId,feedDetails[3]);
        print "</td>";
        #print "<td><b>"feedId"</b></td>";
        print "<td>"text("feedname."feedId,feedDetails[2],"size=10 "attr)"</td>";
        print "<td>"text("feedurl."feedId,feedDetails[4],"size=60 "attr)"</td>";
        print "<td>"select("feedcompression."feedId,feedDetails[5],"1:Yes|0:No",attr)"</td>";
        print "<td>"select("feedpriority."feedId,feedDetails[6],"1:Yes|0:No",attr)"</td>";
        print "<td>"text("feedlinkfind."feedId,feedDetails[7],"size=10 "attr)"</td>";
        print "<td>"text("feedlinkreplace."feedId,feedDetails[8],"size=10 "attr)"</td>";

        rule_count="("rule_count"/"grule_count")";
        if (rule_count == "(0/0)") {
            rule_count = "";
        }
        print "<td>"button("action.editfeed.feedid."feedId,"Filters "rule_count"...")"</td>";
        print "</tr>";
        idlist = idlist g_htmlSep feedId ;
    }
    return idlist;
}

function select(name,value,choices,attr,\
i,html,options,o,lbl,found,sep) {

    split(choices,options,"|");
    html = "<select name=\""name"\" "attr" >";
    for(i = 1; i in options ; i++) {
        lbl = o = options[i];
        if ((sep = index(o,":") ) > 0 ) {
            lbl = substr(o,sep+1);
            o = substr(o,1,sep-1);
        }

        if (o == value) {
            found=1;
        }
        html = html "<option value=\""o"\" " (o == value ? "SELECTED=\"SELECTED\"":"") "   >"lbl"</option>";
    }
    if (found == 0 ) { 
        html = html "<option value=\""value"\" SELECTED=\"SELECTED\"  >"value"</option>";
    }
    html = html "</select>";
    if (attr ~ "\\<disabled\\>" ) {
        html = html hidden(name,value);
    }

    return html;
}

function feedValue(id,name) {
    return g_query[name"."id];
}

function hidden(name,value) {
    return "<input type=hidden name=\""name"\" value=\""value"\" />";
}

function checkbox(name,value,attr) {
    return "<input type=checkbox name=\""name"\" value=\""value"\" "attr" />";
}

function text(name,value,attr) {
    return "<input type=text name=\""name"\" value=\""value"\" "attr" />" (match(attr,"disabled") ? hidden(name,value) : "" );
}

function manageFeed(url,\
id) {
    if ( url ~ "myfeedtime\\.foechoer\\.be" ) {
        if (match(url,"[0-9]+\\.rss")) {
            id = substr(url,RSTART,RLENGTH-4);
            return "<a href=\"http://myfeedtime.foechoer.be/?id="id"\">Edit at http://myfeedtime.foechoer.be</a>";
        }
    }
    return "<a href=\""url"\">"url"</a>";
}

function show_edit_table(feedId,\
global_rule_count,global_rule,rule_count,local_rule) {

    content_title("Edit Listings for feed "   feedValue(feedId,"feedname") " ( " manageFeed(feedValue(feedId,"feedurl"))  " ) ");

    #print "<p>" link2("action","checknew","feedid",feedid,"Check for new nzbs");
    #print "<p>" link("action","reset","Reset/Rewind feed");

    print "<table width=100%><tr>";

    print "<td class=\"rule\" >"
    print "<u>Feed "feedValue(feedId,"feedname")" NZB Filters</u><br>"
    if (g_local_browser) {
        print "<b>+text</b> means text must be present eg +720) (default)<br>"
        print "<b>-text</b> means ext must not be present eg -dvdrip)<br>"
        print "More details via <b>remote browser</b><br>"
    }

    print hidden("feedid",feedId);

    hiddenFeedValues(feedId);
         
    rule_count = loadRules(localRulesFile(feedId),local_rule);
    show_patterns("rules",rule_count,local_rule,18);
    print "</td>";
    
    if (!g_local_browser) {
        print "<td class=\"rule\">"
        print "<center><b>NZB Filters</b></center>";
        print "Add TV program patterns on the left.One on each line."
        print "<br>Each line is converted to a pattern which is matched against Subject titles"
        print "<ul>";
        print "<li>All matching is case insensitive</li>"
        print "<li>A <b>space</b> will match any number of <u><b>non-alphanumeric characters</b></u>.</li>"
        print "<li><span class=\"metachar\">S1</span> will match S01,<span class=\"metachar\">S?</span> will match any season</li>"
        print "<li><span class=\"metachar\">hd</span> will match 720p, or x264</li>"
        print "<li><span class=\"metachar\">sd</span> will match xvid</li>"
        print "<li><span class=\"metachar\">+</span> means the following text <u><b>MUST</b></u> be anywhere in the nzb title.</li>"
        print "<li><span class=\"metachar\">-</span> means the following text must <u><b>NOT</b></u> be in the title.</li>"
        print "<li><span class=\"metachar\">*</span> is the wildcard and matches <u><b>any sequence of characters</b></u>. Most of the time (<span class=\"metachar\">+</span>) is better. Use <span class=\"metachar\">*</span> only if order is important.</li>"
        print "</ul>";
        print "By default patterns start in (+) mode. Examples:"
       print "<br>&quot;<b>Doctor Who<span class=\"metachar\">-</span>Confidential</b>&quot; Will match &quot;Doctor Who&quot; but not the &quot;confidential&quot; episodes."
        print "<br>&quot;<b><span class=\"metachar\">-</span>Confidential<span class=\"metachar\">+</span>Doctor Who</b>&quot; Will do the same thing (note that &quot;Who&quot; is part of the &quot;+&quot; text."
      print "<br> Also due to popular naming convention &quot;<b>Doctor Who<span class=metachar> S?</span></b>&quot; will also limit matches to the main series."
        print "<br>The list is sorted alphabetically each time it is saved"
        print "</td>";
    }
    
    print "</tr><tr>" 
    
    print "<td class=\"grule\">"
    print "<center><u>Global Rules</u></center><br>"

    global_rule_count = loadRules(globalRulesFile(feedId),global_rule);
    show_patterns("grules",global_rule_count,global_rule,4);
    print "</td>";

    if (!g_local_browser) {
        print "<td class=\"grule\">"
        print "<b>Global Rules</b> Add global patterns on the left."
        print "All xvids must match the global patterns<br>"
        print "E.g. For HD only add &quot;<b>+hd</b>&quot;. For SD add &quot;<b>+sd&quot;</b><br>"
        print "To filter programs direct from tv broadcasts try &quot;<b>tv-dvdrip</b>&quot;."
        print "</td>"
    }
    
    print "</tr></table>"
    print two_buttons("save","back");
}

function hiddenFeedValues(feedId,\
feedArr,i) {
    for(i in g_query) {
        if (i ~ "feed.*\\."feedId) {
            print hidden(i,g_query[i]);
        }
    }
}

function two_buttons(b1,b2) {
    return "<table width=100%><tr><td><center>" button("action",b1) "</center></td><td><center>" button("action",b2) "</center></td></tr></table>";
}

#This is called after the form paramters have been parsed.
function start_body_table() {

    head();

    #PCH styles dont seem to be fully supported. So using old way
    print "<body text=\"#999999\" >";
    offset=(systime()/60)%5;
    printf "<table width=\"100%%\" cellpadding=%dpx><tr><td>",offset;
}

function join_query(url,\
u,jq) {
    u="";
    for(jq in g_query) {
        if (u=="") {
            u=url"?"jq"="g_query[jq];
        } else {
            u=u"&"jq"="g_query[jq];
        }
    }
    return u;
}


{ debug($0); }

# Process LOG LINES first -----------------------------------

function font(c,txt) {
   sprintf("<font color=\"%s\">%s</font>",c,txt);
}


/^FORM_PARAMS_BEGIN/,/^FORM_PARAMS_END/ {

        #debug($0);

        if (match($1,"<<.+>>")) {
            name=substr($1,RSTART+2,RLENGTH-4);
            if (match($0,"@@.+@@")) {
                value=substr($0,RSTART+2,RLENGTH-4);
                print "<!-- g_query["name"]=["value"] -->";
                g_query[name]=value;
            }
        }
}


END {

    start_page();

    if (g_query["action"]  ~ "history" ) {

        show_logs("NZB History",g_tv_home "/data/feedtime.history" );

    } else if (g_query["action"] !~ "save|editfeed|config|update|enable|disable|delete" ) {

        show_logs("Activity",g_tv_home "/data/feedtime.out" );

    }

    end_control_form();
    print "</body>";
    print "</html>";
}

function url_encode(text,\
i,c) {
    if (!(1 in _CHR)) { ORD_INIT(); }
    for (i = 1 ; i <= length(text) ; i++ ) {
        c=substr(text,i,1);
        if (index("?& :%=",c) >= 1 || _ORD[c] < 20 ) {
            text = substr(text,1,i-1) _HTML[c] substr(text,i+1);
            i += 2;
        }
    }
    return text;
}

function ORD_INIT(\
i,hex,c) {
    for(i=0 ; i < 255 ; i++ ) {
        c = sprintf("%c",i);
        _CHR[i]=c;
        _ORD[c]=i;
        hex=sprintf("%%%02X",i);
        _HTML[c]=hex;
        _HTML[hex]=c;
    }
}
function url_decode(str,\
start,i,c) {
  start=1;
  #print "URLIN:" str;
  if (!(0 in _CHR)) { ORD_INIT() };

  while ((i=index(substr(str,start),"%")) > 0) {
      i  = (start-1)+i;
      c=toupper(substr(str,i+1,2)); # hex digits
      c=_HTML["%"c];
      str = substr(str,1,i-1) c substr(str,i+3);
      start = i+1;
  }
  #print "URLOUT:" str; 
  return str;
}

#----------------------------------------------------
# HEAPSORT from wikipedia
# Adapted to sorts the data via the index array.
function heapsort (count, data,cmpMethod,\
end,tmp) {
    heapify(count,data,cmpMethod);
    end=count-1;
    while (end > 0) {
        tmp=data[0];data[0]=data[end];data[end]=tmp;
        end--;
        siftdown(data,0,end,cmpMethod);
    }
}
function heapify (count, data,cmpMethod,\
start) {
    start=int((count-2)/2)
    while (start >= 0) {
        siftdown(data,start,count-1,cmpMethod);
        start--;
    }
}
function siftdown (data,start,end,cmpMethod,\
tmp,root,child) {
    root=start;
    while(root*2+1 <= end) {
        child=root*2+1
        if (child+1 <=end && tolower(data[child]) < tolower(data[child+1])) {
            child++;
        }
        if (cmpMethod == 1 && tolower(data[root]) >= tolower(data[child])) {
            return;
        } else if (cmpMethod == 2 && (data[root]+0 >= data[child]+0)) {
            return;
        }
        tmp=data[root];data[root]=data[child];data[child]=tmp;
        root=child;
    }
}

#ENDAWK
  ' "$PROCESS_FORM_VALUES_OUTPUT_FILE"
  rm -f "$PROCESS_FORM_VALUES_OUTPUT_FILE"
  #sed 's/</(/g;s/>/)/g;s/^/<br> /' "$PROCESS_FORM_VALUES_OUTPUT_FILE" 
}

## START OF WRAPPER ##
update_cache=0


#Parse any input
TMPDIR=/share/tmp #/tmp has root only permissions on some NMT
if [ ! -d $TMPDIR ] ; then
    mkdir -p $TMPDIR && chown nmt:nmt $TMPDIR && chmod 777 $TMPDIR 
fi

MAIN_PAGE

# vi:sw=4:et:ts=4
